using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Data;
using Adoor.Object;
using Adoor.Object.Query;
using Adoor.Object.Relational;
using NUnit.Framework;

using Adoor.DAL.Ouvrages;
using Adoor.DAL.Emprunts;
using Adoor.Object.Disconnected;
using Adoor.Relational;


namespace Biblio.NUnit
{
	[TestFixture]
	public class TestLazy : BaseTest
	{
		public ObjectContext Context;

		[SetUp]
		public void Setup()
		{
			Context = CreateContext();

			// Redirect the trace to the NUnit window
			Trace.Listeners.Add(new TextWriterTraceListener(Console.Out, "Console"));
		}

		[TearDown]
		public void TearDown()
		{
			Trace.Listeners.Remove("Console");
		}

		[Test]
		public void TestForeignKeyFactory()
		{
			Exemplaire exemplaire = CreateExemplaire(Context);
			string exemplaireOid = exemplaire.ToString();
			Emprunt emprunt = CreateEmprunt(Context);
			exemplaire.EmpruntCourant = emprunt;
			string empruntOid = emprunt.ToString();
			Context.Update();
			Context.LocalStorage.Clear();
			Exemplaire exemplaireTest = (Exemplaire)Context.Find(typeof(Exemplaire), exemplaireOid);
			// Exemplaire exemplaireTest = Context.Find<Exemplaire>(exemplaireOid); in C# 2
			Assert(exemplaireTest != null);
			Emprunt empruntTest = (Emprunt)Context.Find(typeof(Emprunt), empruntOid);
			// Emprunt empruntTest = Context.Find<Emprunt>(empruntOid); in C# 2
			Assert(empruntTest != null);
			Assert(exemplaireTest.EmpruntCourant == empruntTest);
		}

		[Test]
		public void TestIndirectReferenceFactory()
		{
			Livre livre = CreateLivre(Context);
			string livreOid = livre.ToString();
			Categorie categorie = CreateCategorie(Context);
			string categorieOid = categorie.ToString();
			livre.Categorie = categorie;
			Context.Update();
			Context.LocalStorage.Clear();
			Livre livreTest = (Livre)Context.Find(typeof(Livre), livreOid);
			// Livre livreTest = Context.Find<Livre>(livreOid); in C# 2
			Assert(livreTest != null);
			Categorie categorieTest = (Categorie)Context.Find(typeof(Categorie), categorieOid);
			// Categorie categorieTest = Context.Find<Categorie>(categorieOid); in C# 2
			Assert(categorieTest != null);
			Assert(livreTest.Categorie == categorieTest);
		}

		[Test]
		public void LazyLoading()
		{
			Livre livre1 = CreateLivre(Context);
			string livreOid1 = livre1.ToString();
			Categorie categorie1 = CreateCategorie(Context);
			string categorieOid1 = categorie1.ToString();
			livre1.Categorie = categorie1;

			Livre livre2 = CreateLivre(Context);
			string livreOid2 = livre2.ToString();
			Categorie categorie2 = CreateCategorie(Context);
			string categorieOid2 = categorie2.ToString();
			livre2.Categorie = categorie2;

			Context.Update();
			Context.LocalStorage.Clear();
			
			Livre livreTest1 = (Livre)Context.Find(typeof(Livre), livreOid1);
			// Livre livreTest1 = Context.Find<Livre>(livreOid1); in C# 2
			Assert(livreTest1 != null);

			Livre livreTest2 = (Livre)Context.Find(typeof(Livre), livreOid2);
			//Livre livreTest2 = Context.Find<Livre>(livreOid2); in C# 2
			Assert(livreTest2 != null);

			Categorie categorieTest1 = (Categorie)Context.Find(typeof(Categorie), categorieOid1);
			// Categorie categorieTest1 = Context.Find<Categorie>(categorieOid1); in C# 2
			Assert(categorieTest1 != null);

			Categorie categorieTest2 = (Categorie)Context.Find(typeof(Categorie), categorieOid2);
			// Categorie categorieTest2 = Context.Find<Categorie>(categorieOid2); in C# 2
			Assert(categorieTest2 != null);

			Assert(livreTest1.Categorie == categorieTest1);
			Assert(livreTest2.Categorie == categorieTest2);
		}

		[Test]
		public void FindIsNullAfterDelete()
		{
			Livre livre = CreateLivre(Context);
			string key = livre.ToString();
			Context.Update();
			Context.LinkedDomainCollection[typeof(Livre)].RemoteSource.Delete(livre);
			Context.LocalStorage.Clear();
			Livre livre2 = (Livre)Context.Find(typeof(Livre), key);
			// Livre livre2 = Context.Find<Livre>(key); in C# 2
			AssertNull(livre2);
		}

		[Test]
		public void FindIsNotNullAfterClear()
		{
			Livre livre = CreateLivre(Context);
			string key = livre.ToString();
			Context.Update();
			Context.LocalStorage.Clear();
			Livre livre2 = (Livre)Context.Find(typeof(Livre), key);
			// Livre livre2 = Context.Find<Livre>(key); in C# 2
			AssertNotNull(livre2);
		}

		[Test]
		public void ManualFindIsNullAfterClear()
		{
			Livre livre = CreateLivre(Context);
			string key = livre.ToString();
			Context.Update();
			Context.LocalStorage.Clear();
			Context.Disconnected = true;  // work offline
			Livre livre2 = (Livre)Context.Find(typeof(Livre), key);
			AssertNull(livre2);
		}

		[Test]
		public void CollectAfterPreload()
		{	
			// set up some instances in the database
			CreateLivre(Context);
			CreateLivre(Context);
			Context.Update();
			Context.LocalStorage.Clear();

			// preload the cache
			Context.Preload(typeof(Livre));

			// execute the query on the cache
			ICollection collection = Context.LocalStorage.Collect(typeof(Livre));

			// execute the query on the database
			DataTable table = new DataTable();
            Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(table, typeof(Livre));

			// both results should have the same Count
			Assert(collection.Count == table.Rows.Count);
		}

		[Test]
		public void CollectPreloadAllAfterCreateAndClear()
		{
			// clear all "Livre" from the database
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.DeleteAll(typeof(Livre));

			// set up some instance in the database
			Livre livre1 = CreateLivre(Context);
			string oid1 = livre1.ToString();
			Livre livre2 = CreateLivre(Context);
			string oid2 = livre2.ToString();
			Livre livre3 = CreateLivre(Context);
			string oid3 = livre3.ToString();
			Context.Update();

			// clear & reload the cache
			Context.LocalStorage.Clear();
			Context.Preload(typeof(Livre));

			foreach(Livre l in Context.LocalStorage.Collect(typeof(Livre)))
			// foreach(Livre l in Context.LocalStorage.Collect<Livre>()) in C# 2
			{
				Assert(l.ToString() == oid1 || l.ToString() == oid2 || l.ToString() == oid3);
			}
		}

		[Test]
		public void ViewNxN()
		{
			Livre livre1 = CreateLivre(Context);
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			Auteur auteur2 = CreateAuteur(Context);
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			Context.Update();
			//DataView auteurs = Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill.GetDataView("select Auteur as OID from Livre, Auteur in Livre.Auteur where Livre = :?", livre1);
			DataTable table = new DataTable();
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(table, "select Auteur as OID from Livre, Auteur in Livre.Auteur where Livre = ?", livre1);
			DataView auteurs = table.DefaultView;
			Assert(auteurs.Count == 2);
			Assert(auteurs[0]["OID"] != auteurs[1]["OID"]);
			foreach(DataRowView auteur in auteurs) 
			{
				Assert(string.Compare(auteur["OID"].ToString(), auteur1.ToString(), true) == 0 
                    || string.Compare(auteur["OID"].ToString(), auteur2.ToString(), true) == 0);
			}
		}

        private StringBuilder sqlTrace;

		[Test]
		public void CollectNxNAfterClear()
		{
			Livre livre1 = CreateLivre(Context);
			string livre1Oid = livre1.ToString();
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			string auteur1oid = auteur1.ToString();
			Auteur auteur2 = CreateAuteur(Context);
			string auteur2oid = auteur2.ToString();
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			Context.Update();
			Context.LocalStorage.Clear();

			sqlTrace = new StringBuilder();
            nbQuery = 0;
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace += new QueryTraceEventHandler(TestLazy_QueryTrace);
           
			livre1 = (Livre)Context.Find(typeof(Livre), livre1Oid);
			Assert(sqlTrace.Length != 0);
			sqlTrace.Length = 0;
            nbQuery = 0;


			ICollection auteurs = Context.Collect("select Auteur from  Livre, Auteur in Livre.Auteur where Livre = ?", livre1);
			Assert(auteurs.Count == 2);
			int auteur1count = 0;
			foreach(Auteur auteur in auteurs) 
			{
				Assert(string.Compare(auteur.ToString(), auteur1oid, true) == 0
                    || string.Compare(auteur.ToString(), auteur2oid, true) == 0);
				if (auteur.ToString() == auteur1oid)
					++auteur1count;
			}
			Assert(auteur1count == 1);

			Assert(sqlTrace.Length != 0);
			sqlTrace.Length = 0;
            nbQuery = 0;

			Assert(livre1.Auteur.Count == 2);
			Assert(sqlTrace.Length == 0);  // ListeAuteur must not be fetched again since there is no restriction in the preload query
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace -= new QueryTraceEventHandler(TestLazy_QueryTrace);
        }

        void TestLazy_QueryTrace(object sender, QueryTraceEventArgs e)
        {
            nbQuery++;
            sqlTrace.Append(e.Query);
        }

		[Test]
		public void Preload()
		{
			Livre livre1 = CreateLivre(Context);
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			Auteur auteur2 = CreateAuteur(Context);
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			Context.Update();
			Context.LocalStorage.Clear();

			// Preload all "Livre" with all "Auteur" in "Livre.Auteur"
			Context.Preload("Livre, Auteur in Livre.Auteur");

			// Preload all "Auteur" in "Livre.Auteur" for all "Livre" in the database; do not preload "Livre" (we assume they are already in the cache)
			Context.Preload("(Livre), Auteur in Livre.Auteur");

			// Preload all "Livre" which have "Auteur" in "ListeAuteur", but do not preload "Auteur"
			Context.Preload("Livre, (Auteur in Livre.Auteur)");

			// Preload nothing!
			Context.Preload("(Livre), (Auteur in Livre.Auteur)");
			// TODO: check result			
		}

        int nbQuery;
		[Test]
		public void Preload2()
		{
			Livre livre1 = CreateLivre(Context);
			string livre1Oid = livre1.ToString();
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			string auteur1oid = auteur1.ToString();
			Auteur auteur2 = CreateAuteur(Context);
			string auteur2oid = auteur2.ToString();
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			Context.Update();
			Context.LocalStorage.Clear();

			sqlTrace = new StringBuilder();
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace += new QueryTraceEventHandler(TestLazy_QueryTrace);
           
			livre1 = (Livre)Context.Find(typeof(Livre), livre1Oid);
			Assert(sqlTrace.Length != 0);
			sqlTrace.Length = 0;
            nbQuery = 0;

			//ICollection auteurs = Context.Collect("select Auteur from Livre, Auteur in Livre.Auteur where Livre = :? and Auteur.Nom <> ''", livre1);
			ICollection auteurs = Context.Collect("select Auteur from Livre, Auteur in Livre.Auteur where Livre = ? and Auteur.Nom <> ''", livre1);
			Assert(auteurs.Count == 2);
			int auteur1count = 0;
			foreach(Auteur auteur in auteurs) 
			{
				Assert(auteur.ToString() == auteur1oid || auteur.ToString() == auteur2oid);
				if (auteur.ToString() == auteur1oid)
					++auteur1count;
			}
			Assert(auteur1count == 1);

			Assert(sqlTrace.Length != 0);
			sqlTrace.Length = 0;
            nbQuery = 0;

			Assert(livre1.Auteur.Count == 2);
			Assert(sqlTrace.Length != 0);  // ListeAuteur must be fetched again since there is a restriction in the preload query
            int lineCount = nbQuery;
			Assert(lineCount == 1); // only one line
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace -= new QueryTraceEventHandler(TestLazy_QueryTrace);
        }

		[Test]
		public void Preload3()
		{
			Livre livre1 = CreateLivre(Context);
			string livre1Oid = livre1.ToString();
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			string auteur1oid = auteur1.ToString();
			Auteur auteur2 = CreateAuteur(Context);
			string auteur2oid = auteur2.ToString();
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			Context.Update();
			Context.LocalStorage.Clear();

			sqlTrace = new StringBuilder();
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace += new QueryTraceEventHandler(TestLazy_QueryTrace);
			
			livre1 = (Livre)Context.Find(typeof(Livre), livre1Oid);
			Assert(sqlTrace.Length != 0);
			sqlTrace.Length = 0;
            nbQuery = 0;

			Context.Preload("Livre, Auteur in Livre.Auteur, Livre2 in Auteur.Livre");
			sqlTrace.Length = 0;
            nbQuery = 0;

			foreach(Auteur auteur in livre1.Auteur)
			{
				foreach(Livre livre in auteur.Livre)
				{
				}
			}
			Assert(sqlTrace.Length != 0);  // ListeAuteur be fetched again since there is a restriction (the inner join on Auteur) in the preload query
            int lineCount = nbQuery;
			Assert(lineCount == 2);  // 1 for lookup table, 1 for Auteur
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace -= new QueryTraceEventHandler(TestLazy_QueryTrace);
        }

		[Test]
		public void Preload4()
		{
			Livre livre1 = CreateLivre(Context);
			string livre1Oid = livre1.ToString();
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			string auteur1oid = auteur1.ToString();
			Auteur auteur2 = CreateAuteur(Context);
			string auteur2oid = auteur2.ToString();
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			Context.Update();
			Context.LocalStorage.Clear();

			sqlTrace = new StringBuilder();
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace += new QueryTraceEventHandler(TestLazy_QueryTrace);
			
			livre1 = (Livre)Context.Find(typeof(Livre), livre1Oid);
			Assert(sqlTrace.Length != 0);
			sqlTrace.Length = 0;
            nbQuery = 0;

			Context.Preload("Livre, Auteur in Livre.Auteur, Livre2 in Auteur.Livre?");
			sqlTrace.Length = 0;
            nbQuery = 0;

			foreach(Auteur auteur in livre1.Auteur)
			{
				foreach(Livre livre in auteur.Livre)
				{
				}
			}
			Assert(sqlTrace.Length == 0);  // ListeAuteur must not be fetched again since there is no restriction in the preload query
			// the outer join on Auteur is not a restriction
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace -= new QueryTraceEventHandler(TestLazy_QueryTrace);
        }

		[Test]
		public void Preload5()
		{
			Livre livre1 = CreateLivre(Context);
			string livre1Oid = livre1.ToString();
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			string auteur1oid = auteur1.ToString();
			Auteur auteur2 = CreateAuteur(Context);
			string auteur2oid = auteur2.ToString();
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			Context.Update();
			Context.LocalStorage.Clear();

			sqlTrace = new StringBuilder();
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace += new QueryTraceEventHandler(TestLazy_QueryTrace);
            
			livre1 = (Livre)Context.Find(typeof(Livre), livre1Oid);
			Assert(sqlTrace.Length != 0);
			sqlTrace.Length = 0;
            nbQuery = 0;

			//Context.Preload("Livre, Auteur in Livre.Auteur, Livre2 in Auteur.Livre where Livre2 = :?", livre1);
			Context.Preload("Livre, Auteur in Livre.Auteur, Livre2 in Auteur.Livre where Livre2 = ?", livre1);

			sqlTrace.Length = 0;
            nbQuery = 0;

			foreach(Auteur auteur in livre1.Auteur)
			{
				foreach(Livre livre in auteur.Livre)
				{
				}
			}
			Assert(sqlTrace.Length != 0);  // ListeAuteur & ListeLivre must be fetched again since there is a restriction (at the 2nd level) in the preload query
			int lineCount = nbQuery; 
			Assert(lineCount == 6);  // 2 * ListeAuteur(=1) + 2 * ListeLivre(=2)
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace -= new QueryTraceEventHandler(TestLazy_QueryTrace);
        }

		[Test]
		public void Preload6()
		{
			Livre livre1 = CreateLivre(Context);
			string livre1Oid = livre1.ToString();
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			string auteur1oid = auteur1.ToString();
			Auteur auteur2 = CreateAuteur(Context);
			string auteur2oid = auteur2.ToString();
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			Context.Update();
			Context.LocalStorage.Clear();

			sqlTrace = new StringBuilder();
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace += new QueryTraceEventHandler(TestLazy_QueryTrace);
            
			livre1 = (Livre)Context.Find(typeof(Livre), livre1Oid);
			Assert(sqlTrace.Length != 0);
			sqlTrace.Length = 0;
            nbQuery = 0;

			//Context.Preload("Livre, Auteur in Livre.Auteur, Livre2 in Auteur.Livre? where Livre2 = :?", livre1);
			Context.Preload("Livre, Auteur in Livre.Auteur, Livre2 in Auteur.Livre? where Livre2 = ?", livre1);
			sqlTrace.Length = 0;
            nbQuery = 0;

			foreach(Auteur auteur in livre1.Auteur)
			{
				foreach(Livre livre in auteur.Livre)
				{
				}
			}
			Assert(sqlTrace.Length != 0);  // ListeLivre must be fetched again since there is a restriction (at the 2nd level) in the preload query
            int lineCount = nbQuery; // ListeAuteur must not be fetched again since ListeLivre is an outer join
			Assert(lineCount == 4); // 2 * (ListeLivre(=2))
            ((IDbRelationalSource)((RelationalObjectSource)Context.LinkedDomainCollection[0].RemoteSource).RelationalSource).QueryTrace -= new QueryTraceEventHandler(TestLazy_QueryTrace);
        }

		[Test]
		public void NavigateNxN()
		{
			Livre livre1 = CreateLivre(Context);
			string livre1oid = livre1.ToString();
			Auteur auteur1 = CreateAuteur(Context);
			string auteur1oid = auteur1.ToString();
			Auteur auteur2 = CreateAuteur(Context);
			string auteur2oid = auteur2.ToString();
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			Context.Update();
			Context.LocalStorage.Clear();
			// TODO: clear trace
			Livre livre3 = (Livre)Context.Find(typeof(Livre), livre1oid);
			// TODO: 1 SQL line in trace
			// TODO: clear trace
			Assert(livre3 != null);
			// TODO: clear trace
			Assert(livre3.Auteur.Count == 2);
			// TODO: 1 SQL line in trace
			// TODO: clear trace
			foreach(Auteur auteur in livre3.Auteur) 
			{
				Assert(auteur.ToString() == auteur1oid || auteur.ToString() == auteur2oid);
			}
			// TODO: 1 SQL line in trace
			// TODO: clear trace
			int auteur1count = 0;
			foreach(Auteur auteur in livre3.Auteur) 
			{
				Assert(auteur.ToString() == auteur1oid || auteur.ToString() == auteur2oid);
				if (auteur.ToString() == auteur1oid)
					++auteur1count;
			}
			Assert(auteur1count == 1);
			// TODO: 0 SQL line in trace
		}

		[Test]
		public void CollectNxN()
		{
			Livre livre1 = CreateLivre(Context);
			Livre livre2 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			Auteur auteur2 = CreateAuteur(Context);
			livre1.Auteur.Add(auteur1);
			livre1.Auteur.Add(auteur2);
			auteur2.Livre.Add(livre2);
			Context.Update();
			//ICollection auteurs = Context.LocalStorage.Collect("select Auteur from Livre, Auteur in Livre.Auteur where Livre = :?", livre1);
			ICollection auteurs = Context.LocalStorage.Collect("select Auteur from Livre, Auteur in Livre.Auteur where Livre = ?", livre1);
			Assert(auteurs.Count == 2);
			int auteur1count = 0;
			foreach(Auteur auteur in auteurs) 
			{
				Assert(auteur == auteur1 || auteur == auteur2);
				if (auteur == auteur1)
					++auteur1count;
			}
			Assert(auteur1count == 1);
		}

		[Test]
		public void TestMultipleOID()
		{
			Livre livre1 = CreateLivre(Context);
			Auteur auteur1 = CreateAuteur(Context);
			Categorie categorie1 = CreateCategorie(Context);
			livre1.Auteur.Add(auteur1);
			livre1.Categorie = categorie1;
			Context.Update();
			//DataView auteurs = Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill.GetDataView("select Auteur, Categorie from Livre, Auteur in Livre.Auteur, Livre.Categorie? where Auteur = :? and Categorie = :?", auteur1, categorie1);
			DataTable table = new DataTable();
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(table, "select Auteur, Categorie from Livre, Auteur in Livre.Auteur, Livre.Categorie? where Auteur = ? and Categorie = ?", auteur1, categorie1);
		}

        //[Test]
        //public void TestMinus()
        //{
        //    Livre livre1 = CreateLivre(Context);
        //    Auteur auteur1 = CreateAuteur(Context);
        //    Categorie categorie1 = CreateCategorie(Context);
        //    livre1.Auteur.Add(auteur1);
        //    livre1.Categorie = categorie1;
        //    Context.Update();
        //    ObjectQuery query1 = Context.ObjectResolver.ParseQuery("Livre");
        //    ObjectQuery query2 = Context.ObjectResolver.ParseQuery("select Livre2 from Livre Livre2, Auteur in Livre2.Auteur?, Livre2.Categorie, Test in Auteur.Test where Auteur = ? AND Categorie = ?");
        //    query2.Distinct = true;
        //    ObjectQuery query3 = new ObjectQuery(query1.Path.Minus(query2.Path), null, false, null, -1);
        //    long c1 = Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill.GetCount(query1, null);
        //    long c3 = Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill.GetCount(query2, new object[] {auteur1, categorie1});
        //    long c2 = Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill.GetCount(query3, new object[] {auteur1, categorie1});
        //    Assert(c1 == c2 + c3);
        //}

        //[Test]
        //public void TestInverseForeignKey()
        //{
        //    Livre livre1 = CreateLivre(Context);
        //    Auteur auteur1 = CreateAuteur(Context);
        //    Categorie categorie1 = CreateCategorie(Context);
        //    livre1.Auteur.Add(auteur1);
        //    livre1.Categorie = categorie1;
        //    Context.Update();
        //    DataTable table = new DataTable();
        //    Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(table, "select Auteur.*, Test.Contribution from Auteur, Test in Auteur.Test");
        //}


		[Test]
		public void TestCross()
		{
			DataSet dataset = new DataSet();
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "Livre, Livre.Categorie, Livre Livre2 where Livre.Nom = Livre2.Nom");

			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "Livre, Livre.Categorie, Livre Livre2 where Livre.Nom = Livre2.Nom");

			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "Livre, Livre.Categorie, Livre as Livre2 where Livre.Nom = Livre2.Nom");
		}

        //[Test]
        //public void TestEscape()
        //{
        //    // {} is an escape sequence whose content is transmitted as such to the database
        //    DataTable table = new DataTable();
        //    Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(table, "select {'Nom = ' + Nom2} as nom from Livre");
        //}

		[Test, ExpectedException(typeof(ParseException))]
		public void TestWrongselector()
		{
			DataTable table = new DataTable();
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(table, "select Auteur.Nom from Livre");
		}

        //[Test]
        //public void TestEnum()
        //{
        //    Revue revue = (Revue)Context.LocalStorage.Create(typeof(Revue));
        //    revue.Frequence = FrequenceType.Mensuel;
        //    string revueId = revue.ToString();
        //    Context.Update();
        //    Context.LocalStorage.Clear();
        //    revue = (Revue)Context.Find(typeof(Revue), revueId);
        //    Assert(revue != null);
        //    Assert(revue.Frequence == FrequenceType.Mensuel);
        //}

		[Test]
		public void TestQueries()
		{
			DataSet dataset = new DataSet();
			//Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "Auteur");
			//Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "Auteur, Livre in Auteur.Livre");
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "select Auteur.Nom from Auteur");
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "select Auteur.Nom, Auteur.Prenom from Auteur");
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "select Auteur.* from Auteur");
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "select Auteur.Nom, Livre.Nom from Auteur, Livre in Auteur.Livre");
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "Livre, Livre.Categorie, Livre as Livre2 where Livre.Nom = Livre2.Nom");
			//Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "select Livre.Nom, {'Nom = ' + Nom2} as Libelle from Livre");
			//Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "Livre where {Nom2} = Livre.Nom");
			Context.LinkedDomainCollection.CrossLinkedDomainGroupRemoteSource.Fill(dataset, "select 'Nom = ' + Livre.Nom as nom from Livre");
		}
	}
}